﻿using HMS.Core.Abstractions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;

namespace HMS.Hosting.Authentication;

public class DefaultAuthenticationOptions : AuthenticationSchemeOptions
{
    #region TokenRetriever   
    public Func<HttpRequest, string> TokenRetriever { get; set; } = (request) =>
    {
        var authorization = request.Headers["Authorization"].FirstOrDefault();

        if (string.IsNullOrEmpty(authorization))
        {
            return string.Empty;
        }

        var scheme = JwtBearerDefaults.AuthenticationScheme;

        return authorization.StartsWith(scheme + " ", StringComparison.OrdinalIgnoreCase)
            ? authorization[(scheme.Length + 1)..].Trim()
            : string.Empty;
    };
    #endregion
}

public class DefaultAuthenticationHandlerPlatform : AuthenticationHandler<DefaultAuthenticationOptions>
{
    private readonly ITenantService _tenantService;

    public DefaultAuthenticationHandlerPlatform(
        IOptionsMonitor<DefaultAuthenticationOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock,
        ITenantService tenantService)
        : base(options, logger, encoder, clock)
    {
        _tenantService = tenantService;
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var tenantId = Context.Request.Cookies["tenant"];

        if (!string.IsNullOrEmpty(tenantId))
        {
            _tenantService.SetTenantId(tenantId);
        }

        try
        {
            var authResult = await Context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);

            return authResult.Succeeded
                ? AuthenticateResult.Success(new AuthenticationTicket(authResult.Principal, CookieAuthenticationDefaults.AuthenticationScheme))
                : AuthenticateResult.Fail("Unauthorized");
        }
        catch (Exception ex)
        {
            return AuthenticateResult.Fail(ex);
        }
    }
}